package com.linkdood.app.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.linkdood.app.constants.DateConstants;
import com.linkdood.app.constants.LinkDoodConstants;
import com.linkdood.app.domain.MessageTemplate;
import com.linkdood.app.domain.NoticeMessage;
import com.linkdood.app.domain.ThirdParty;
import com.linkdood.app.enums.MessageStatusEnum;
import com.linkdood.app.mapper.MessageTemplateMapper;
import com.linkdood.app.mapper.NoticeMessageMapper;
import com.linkdood.app.service.DdioService;
import com.linkdood.app.service.MessageScannerService;
import com.linkdood.app.service.NoticeMessageService;
import com.linkdood.app.service.ThirdPartyService;
import com.linkdood.app.service.ddio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 消息定时扫描类
 */
@Slf4j
@Service
public class MessageScannerServiceImpl implements MessageScannerService {

    private final ThirdPartyService thirdPartyService;

    private final MessageTemplateMapper messageTemplateMapper;

    private final NoticeMessageMapper noticeMessageMapper;

    private final NoticeMessageService noticeMessageService;

    private final DdioService ddioService;

    public MessageScannerServiceImpl(ThirdPartyService thirdPartyService, MessageTemplateMapper messageTemplateMapper,
                                     NoticeMessageMapper noticeMessageMapper, NoticeMessageService noticeMessageService,
                                     DdioService ddioService) {
        this.thirdPartyService = thirdPartyService;
        this.messageTemplateMapper = messageTemplateMapper;
        this.noticeMessageMapper = noticeMessageMapper;
        this.noticeMessageService = noticeMessageService;
        this.ddioService = ddioService;
    }

    /**
     * 定时消息
     */
    @Override
    public void scanTemplateMessage() {
        log.debug("start scan message, thread name is : {}", Thread.currentThread().getName());
        LocalDateTime endLocalDate = LocalDateTime.now();
        LocalDateTime startLocalDate = endLocalDate.plusDays(-1);
        String startTime = startLocalDate.format(DateTimeFormatter.ofPattern(DateConstants.NORMAL));
        String endTime = endLocalDate.format(DateTimeFormatter.ofPattern(DateConstants.NORMAL));
        List<ThirdParty> thirdPartyList = thirdPartyService.listByThirdsType(1);
        for (ThirdParty thirdParty : thirdPartyList) {
            List<NoticeMessage> noticeMessageList = noticeMessageService.getByThirdIdAndStarTime(thirdParty.getId(), startTime, endTime);
            if (noticeMessageList.isEmpty()) {
                continue;
            }

            for (NoticeMessage noticeMessage : noticeMessageList) {
                try {
                    if (StringUtils.isBlank(noticeMessage.getToUsers())) {
                        log.warn("exit send message, message id : {}, exit info : toUsers is null", noticeMessage.getId());
                        continue;
                    }

                    this.sendMessage(noticeMessage);
                } catch (Exception e) {
                    log.error("message send error, message id : {}, error info : {}", noticeMessage.getId(), e);
                    NoticeMessage message = new NoticeMessage();
                    message.setId(noticeMessage.getId());
                    if (Integer.valueOf(0).equals(noticeMessage.getStatus())) {
                        message.setStatus(2);
                        log.debug("message send error, message id : {} ,change status form {} to {}", noticeMessage.getId(), 0, 2);
                    } else if (Integer.valueOf(2).equals(noticeMessage.getStatus())) {
                        message.setStatus(3);
                        log.debug("message send error, message id : {} ,change status form {} to {}", noticeMessage.getId(), 2, 3);
                    }

                    message.setDealTime(LocalDateTime.now());
                    noticeMessageMapper.updateById(message);
                }
            }
        }
    }

    /**
     * 添加模板消息的公用内容
     */
    private void createTemplateMessage(TemplateMessage templateMessage, NoticeMessage noticeMessage) {
        templateMessage.setCreator("App Template");
        templateMessage.setContent(noticeMessage.getContent());
        templateMessage.setDetailUrl(noticeMessageService.getMessageUrl(noticeMessage.getId()));
        templateMessage.setTitle(noticeMessage.getTitle());
        if (noticeMessage.getTitleBackgroundColor() == null) {
            templateMessage.setTitleBgColor("#4CB7EA");
        } else {
            templateMessage.setTitleBgColor(noticeMessage.getTitleBackgroundColor());
        }
        templateMessage.setTitleColor("#FFFFFF");
        templateMessage.setToUsers(noticeMessage.getToUsers());
        templateMessage.setType("1");
    }

    /**
     * 创建普通模板消息对象
     */
    private TemplateMessage createCommonTemplateMessage(NoticeMessage noticeMessage) {
        TemplateMessage templateMessage = new TemplateMessage();
        createTemplateMessage(templateMessage, noticeMessage);
        if (StringUtils.isNotBlank(noticeMessage.getReserve1())) {
            JSONObject messageJson = JSON.parseObject(noticeMessage.getReserve1());
            Iterator<Map.Entry<String, Object>> msgSetIter = messageJson.entrySet().iterator();
            List<Map<String, String>> fields = new ArrayList<>();
            while (msgSetIter.hasNext()) {
                Map.Entry<String, Object> entry = msgSetIter.next();
                Map<String, String> field = new HashMap<>(16);
                field.put(entry.getKey(), (String) entry.getValue());
                fields.add(field);
            }
            templateMessage.setFields(fields);
        }
        return templateMessage;
    }

    /**
     * 创建带按钮交互的模板消息对象
     */
    private TemplateMessageContent createInteractTemplateMessage(NoticeMessage noticeMessage, UUID uuid) {
        TemplateMessageContent templateMessage = new TemplateMessageContent();
        createTemplateMessage(templateMessage, noticeMessage);
        if (StringUtils.isNotBlank(noticeMessage.getReserve1())) {
            JSONObject messageJson = JSON.parseObject(noticeMessage.getReserve1());
            Iterator<Map.Entry<String, Object>> msgSetIter = messageJson.entrySet().iterator();
            List<Map<String, String>> fields = new ArrayList<>();
            while (msgSetIter.hasNext()) {
                Map.Entry<String, Object> entry = msgSetIter.next();
                Map<String, String> field = new HashMap<>(16);
                field.put(entry.getKey(), (String) entry.getValue());
                fields.add(field);
            }
            templateMessage.setFields(fields);
        }
        templateMessage.setBId(uuid.toString());
        List<TemplateMessageButton> list = new ArrayList<>();
        TemplateMessageButton button1 = new TemplateMessageButton();
        button1.setCnName("同意");
        button1.setEnName("agree");
        button1.setEventType(LinkDoodConstants.TEMPLATE_MESSAGE_EVENT_TYPE_AGREE);
        button1.setIsInput("true");
        list.add(button1);

        TemplateMessageButton button2 = new TemplateMessageButton();
        button2.setCnName("拒绝");
        button2.setEnName("refuse");
        button2.setEventType(LinkDoodConstants.TEMPLATE_MESSAGE_EVENT_TYPE_REFUSE);
        button2.setIsInput("true");
        list.add(button2);
        templateMessage.setButtons(list);
        return templateMessage;
    }

    /**
     * 创建带按钮交互的返回模板消息
     */
    private TemplateMessageResult createResultTemplateMessage(NoticeMessage noticeMessage) {
        TemplateMessageResult templateMessage = new TemplateMessageResult();
        createTemplateMessage(templateMessage, noticeMessage);
        if (StringUtils.isNotBlank(noticeMessage.getReserve1())) {
            JSONObject messageJson = JSON.parseObject(noticeMessage.getReserve1());
            templateMessage.setEventData(messageJson);
        }
        if (StringUtils.isNotBlank(noticeMessage.getReserve2())) {
            templateMessage.setBId(noticeMessage.getReserve2());
        }
        if (StringUtils.isNotBlank(noticeMessage.getReserve3())) {
            templateMessage.setMToken(noticeMessage.getReserve3());
        }
        return templateMessage;
    }

    /**
     * 发送消息
     */
    @Override
    public void sendMessage(NoticeMessage noticeMessage) {
        if (noticeMessage.getType().equals(LinkDoodConstants.TEMPLATE_MESSAGE_TYPE_APPROVE_SEND)) {
            if (noticeMessage.getToUsers() != null || noticeMessage.getToUsers().contains(",")) {
                for (String userId : noticeMessage.getToUsers().split(",")) {
                    noticeMessage.setToUsers(userId);
                    UUID uuid = UUID.randomUUID();
                    sendAndDealResult(createInteractTemplateMessage(noticeMessage, uuid), noticeMessage, uuid);
                }
            }
        } else if (noticeMessage.getType().equals(LinkDoodConstants.TEMPLATE_MESSAGE_TYPE_APPROVE_RESULT)) {
            sendAndDealResult(createResultTemplateMessage(noticeMessage), noticeMessage, null);
        } else {
            sendAndDealResult(createCommonTemplateMessage(noticeMessage), noticeMessage, null);
        }
    }

    /**
     * 发送消息，并根据消息返回结果更新消息发送状态
     */
    private void sendAndDealResult(TemplateMessage templateMessage, NoticeMessage noticeMessage, UUID uuid) {
        DdioResponseBody resp = ddioService.sendTemplate2Users(templateMessage, noticeMessage.getThirdPartyId());
        dealTemplateMessageResult(noticeMessage, uuid, resp);
    }

    /**
     * 处理消息返回结果
     */
    @Override
    public void dealTemplateMessageResult(NoticeMessage noticeMessage, UUID uuid, DdioResponseBody resp) {
        if (resp.getCode().equals(0)) {
            if (noticeMessage.getType().equals(LinkDoodConstants.TEMPLATE_MESSAGE_TYPE_APPROVE_SEND)) {
                MessageTemplate messageTemplate = new MessageTemplate();
                messageTemplate.setBid(uuid.toString());
                messageTemplate.setThirdPartyId(noticeMessage.getThirdPartyId());
                messageTemplate.setUserId(noticeMessage.getToUsers());
                messageTemplate.setFromUserId(noticeMessage.getFromUser());
                messageTemplate.setCreateTime(LocalDateTime.now());
                messageTemplate.setUpdateTime(LocalDateTime.now());
                messageTemplate.setStatus(MessageStatusEnum.PENDING);
                messageTemplate.setParam(noticeMessage.getReserve3());
                messageTemplateMapper.insert(messageTemplate);
            }
            NoticeMessage result = new NoticeMessage();
            result.setId(noticeMessage.getId());
            result.setStatus(1);
            result.setDealTime(LocalDateTime.now());
            this.noticeMessageMapper.updateById(result);
            log.debug("message send success, messageId: {}, return message: {}", noticeMessage.getId(), resp.getMsg());
        } else {
            log.warn("message send error, messageId: {}, return message: {}", noticeMessage.getId(), resp.getMsg());
            NoticeMessage result = new NoticeMessage();
            result.setId(noticeMessage.getId());
            if (Integer.valueOf(0).equals(noticeMessage.getStatus())) {
                result.setStatus(2);
                log.debug("message send error, messageId: {}, change status form {} to {}", noticeMessage.getId(), 0, 2);
            } else if (Integer.valueOf(2).equals(noticeMessage.getStatus())) {
                result.setStatus(3);
                log.debug("message send error, messageId: {}, change status form {} to {}", noticeMessage.getId(), 2, 3);
            }

            result.setDealTime(LocalDateTime.now());
            noticeMessageMapper.updateById(result);
        }
    }
}
